package com.yss.reportworld.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yss.common.core.constant.RequestDataHelper;
import com.yss.common.core.domain.TreeNode;
import com.yss.common.core.enums.YssStatusEnum;
import com.yss.common.core.exception.BusinessException;
import com.yss.common.core.utils.StringUtils;
import com.yss.common.core.utils.uuid.IdUtils;
import com.yss.common.security.utils.SecurityUtils;
import com.yss.reportworld.domain.DataReport;
import com.yss.reportworld.domain.Report;
import com.yss.reportworld.mapper.DataReportMapper;
import com.yss.reportworld.util.TableInfoUtil;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yss.reportworld.service.IReportService;
import com.yss.reportworld.mapper.ReportMapper;

/**
 * 报表信息Service业务层处理
 *
 * @author yss
 * @date 2023-03-24
 */
@Slf4j
@Service
public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> implements IReportService {
    @Autowired
    private DataReportMapper dataReportMapper;

    /**
     * 查询报表信息列表
     *
     * @param report 报表信息
     * @return 报表信息
     */
    @Override
    public List<Report> selectReportList(Report report) {
        try {
            TableInfoUtil.handleTableVersion(report.getHisVersion()); // 替换表名
            QueryWrapper<Report> wrapper = new QueryWrapper();
            wrapper.orderByDesc("STATUS");
            wrapper.orderByAsc("PARENT_ID,ORDER_NUM");
            if (StringUtils.isNotEmpty(report.getName())) {
                wrapper.like("NAME", report.getName());
            }
            if (StringUtils.isNotEmpty(report.getVersion())) {
                wrapper.eq("VERSION", report.getVersion());
            }
            if (null != report.getStatus()) {
                wrapper.eq("STATUS", report.getStatus());
            }
            return this.list(wrapper);

        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 查询报表信息
     *
     * @param report
     * @return
     */
    public Report selectReportById(Report report) {
        try {
            TableInfoUtil.handleTableVersion(report.getHisVersion()); // 替换表名
            return this.getById(report.getId());
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 查询报表树结构信息
     *
     * @return 报表树信息集合
     */
    public List<TreeNode> selectReportTreeList() {
        List<TreeNode> list = new ArrayList<>();
        QueryWrapper<Report> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("PARENT_ID,ORDER_NUM");
        wrapper.eq("STATUS", YssStatusEnum.NORMAL.getCode());
        List<Report> listReport = this.list(wrapper);
        if (StringUtils.isEmpty(listReport)) {
            return list;
        }
        List<String> tempList = listReport.stream().map(Report::getId).collect(Collectors.toList());
        Set<String> set = new HashSet<>();
        for (Report report : listReport) {
            if (set.contains(report.getParentId()) || tempList.contains(report.getParentId())) {
                continue;
            }
            list.addAll(this.recursionTree(report.getParentId(), listReport));
            set.add(report.getParentId());
        }
        return list;
    }

    private List<TreeNode> recursionTree(String id, List<Report> listReport) {
        List<TreeNode> list = new ArrayList<>();
        for (Report report : listReport) {
            if (!id.equals(report.getParentId())) {
                continue;
            }
            TreeNode treeNode = this.handReportToNode(report);
            List<TreeNode> children = recursionTree(report.getId(), listReport);
            treeNode.setChildren(children);
            list.add(treeNode);
        }
        return list;
    }

    /**
     * 将业务功能转化成TreeNode
     */
    private TreeNode handReportToNode(Report report) {
        TreeNode node = new TreeNode();
        node.setId(report.getId());
        node.setParentId(report.getParentId());
        node.setLabel(report.getName());
        return node;
    }

    /**
     * 递归查询所有下级报表ID集合
     *
     * @param id
     * @return
     * @throws Exception
     */
    public List<String> queryReportIds(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("获取报表信息失败，请稍后重试！");
        }
        List<String> strList = new ArrayList<>();
        List<Report> list = this.list(new QueryWrapper<>());
        recursionIds(id, strList, list);
        return strList;
    }

    private void recursionIds(String id, List<String> strList, List<Report> list) {
        for (Report report : list) {
            if (!id.equals(report.getParentId())) {
                continue;
            }
            strList.add(report.getId());
            recursionIds(report.getId(), strList, list);
        }
    }


    /**
     * 添加报表信息
     *
     * @param report
     * @throws Exception
     */
    public boolean addReport(Report report) {
        try {
            if (StringUtils.isNull(report)) {
                throw new BusinessException("获取模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(report.getHisVersion()); // 替换表名
            if (!this.checkNameUnique(report)) {
                throw new BusinessException("报表名称【" + report.getName() + "】已存在");
            }
            String id = IdUtils.fastSimpleUUID();
            report.setId(id);
            report.setStatus(YssStatusEnum.NORMAL.getCode());
            report.setCreateBy(SecurityUtils.getUsername());
            report.setCreateTime(new Date());
            if ("0".equals(report.getParentId())) {
                return this.save(report);
            }
            //添加之前没有下级模块的数据的 添加了以后 模块的关联关系修改到下级
            // 获取该模块的上级之前是不是最明细的
            QueryWrapper<Report> wrapper = new QueryWrapper<>();
            wrapper.eq("PARENT_ID", report.getParentId());
            List<Report> list = this.list(wrapper);
            if (StringUtils.isEmpty(list)) { //添加的上级以前没有下级
                // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
                UpdateWrapper<DataReport> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("REPORT_ID", report.getParentId());
                DataReport dataReport = new DataReport();
                dataReport.setReportId(id);
                dataReportMapper.update(dataReport, updateWrapper);
            }
            return this.save(report);
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 修改报表信息
     *
     * @param report
     * @throws Exception
     */
    public boolean editReport(Report report) {
        try {
            if (StringUtils.isNull(report) || StringUtils.isBlank(report.getId())) {
                throw new BusinessException("获取模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(report.getHisVersion()); // 替换表名
            if (!this.checkNameUnique(report)) {
                throw new BusinessException("报表名称【" + report.getName() + "】已存在");
            }
            // 修改之前的上级只有一个下级
            Report oldReport = this.getById(report.getId());
            QueryWrapper<Report> wrapperOld = new QueryWrapper<>();
            wrapperOld.eq("PARENT_ID", oldReport.getId());
            List<Report> listOld = this.list(wrapperOld);
            if (StringUtils.isEmpty(listOld)) { //修改之前没有下级
                QueryWrapper<Report> wrapper = new QueryWrapper<>();
                wrapper.eq("PARENT_ID", oldReport.getParentId());
                List<Report> list = this.list(wrapper);
                if (!StringUtils.isEmpty(list) && list.size() == 1) {
                    // 原来的关联表是这个明细的ID 更新成现在将会变成明细的上级ID
                    UpdateWrapper<DataReport> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("REPORT_ID", oldReport.getId());
                    DataReport dataReport = new DataReport();
                    dataReport.setReportId(oldReport.getParentId());
                    dataReportMapper.update(dataReport, updateWrapper);
                }
            }
            report.setUpdateTime(new Date());
            report.setUpdateBy(SecurityUtils.getUsername());
            //修改后的上级
            if ("0".equals(report.getParentId())) {
                return this.updateById(report);
            }
            // 修改后的这上级 之前是否存在下级
            QueryWrapper<Report> wrapper = new QueryWrapper<>();
            wrapper.eq("PARENT_ID", report.getParentId());
            List<Report> list = this.list(wrapper);
            if (StringUtils.isEmpty(list)) { //添加的上级以前没有下级
                // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
                UpdateWrapper<DataReport> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("REPORT_ID", report.getParentId());
                DataReport dataReport = new DataReport();
                dataReport.setReportId(report.getId());
                dataReportMapper.update(dataReport, updateWrapper);
            }
            return this.updateById(report);
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 删除报表信息
     *
     * @param report
     * @throws Exception
     */
    public boolean delReport(Report report) {
        try {
            if (StringUtils.isBlank(report.getId())) {
                throw new BusinessException("获取删除模块信息失败，请稍后重试！");
            }
            TableInfoUtil.handleTableVersion(report.getHisVersion()); // 替换表名
            QueryWrapper<Report> reportQueryWrapper1 = new QueryWrapper<>();
            reportQueryWrapper1.eq("PARENT_ID", report.getId());
            List<Report> list = this.list(reportQueryWrapper1);
            if (list.size() > 0) {
                throw new BusinessException("存在下级报表,不允许删除");
            }
            //  List<String> list = this.queryReportIds(id); //所有下级模块
            Report oldReport = this.getById(report.getId());
            // 删除的这个ID 不是一个一级的
            if ("0".equals(oldReport.getParentId())) {
                // 删除关联关系表中所所有改id包括所有下级的
                QueryWrapper<DataReport> wrapper = new QueryWrapper<>();
                wrapper.in("REPORT_ID", report.getId());
                dataReportMapper.delete(wrapper);
                return this.removeById(report.getId());
            }
            UpdateWrapper<DataReport> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("REPORT_ID", report.getId());
            DataReport dataReport = new DataReport();
            dataReport.setReportId(oldReport.getParentId());
            dataReportMapper.update(dataReport, updateWrapper);
            return this.removeById(report.getId());
        } finally {
            RequestDataHelper.removeThreadLocal();
        }
    }

    /**
     * 获取报表信息
     *
     * @return
     * @throws Exception
     */
    public Map<String, Report> getReportMap() {
        Map<String, Report> mapReport = new HashMap<>();
        QueryWrapper<Report> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("NAME");
        List<Report> listReport = this.list(wrapper);
        if (StringUtils.isEmpty(listReport)) {
            return null;
        }
        for (Report report : listReport) {
            if (StringUtils.isNull(report) || StringUtils.isBlank(report.getId())) {
                continue;
            }
            mapReport.put(report.getId(), report);
        }
        return mapReport;
    }

    /**
     * 报表数据的json
     *
     * @return
     * @throws Exception
     */
    public String getReportJsonInfo() {
        String[] includeProperties = {"id", "parentId", "name", "status"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter includefilter = filters.addFilter();
        includefilter.addIncludes(includeProperties);
        QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("STATUS", YssStatusEnum.getUpgradeToolsZipStatus());
        queryWrapper.orderByAsc("NAME");
        List<Report> list = this.list(queryWrapper);
        return JSONObject.toJSONString(list, includefilter, SerializerFeature.WriteMapNullValue);
    }

    /**
     * 校验报表名称是否唯一
     *
     * @param report
     * @return 结果
     */
    private boolean checkNameUnique(Report report) {
        String reportId = StringUtils.isNull(report.getId()) ? "-1" : report.getId();
        QueryWrapper<Report> wrapper = new QueryWrapper<>();
        wrapper.eq("NAME", report.getName());
        wrapper.eq("PARENT_ID", report.getParentId());
        Report info = this.getOne(wrapper);
        if (StringUtils.isNotNull(info) && !info.getId().equals(reportId)) {
            return false;
        }
        return true;
    }
}
